<?php

namespace App\Third\Service\Wx;


use App\Common\Constants\ErrorCode;
use App\Common\Exception\RefundException;
use App\Common\Service\BaseService;
use App\Third\Event\WxPush;
use GuzzleHttp\Exception\ClientException;
use GuzzleHttp\Exception\ServerException;
use Hyperf\Di\Annotation\Inject;
use Hyperf\Guzzle\ClientFactory;
use Psr\EventDispatcher\EventDispatcherInterface;

/**
 * http://doc.wuuxiang.com/showdoc/web/#/11?page_id=263(三方文档地址)
 * Class WxMainDeliverService
 * @package App\Third\Service\Wx
 */

class WxMainDeliverService extends BaseService
{

    /**
     * 生成外卖单接口（不对接基础档案）
     */
    const CRM_DELIVERY_URL = '/delivery/DeliveryInsertOfflineMapping.htm';

    const CRM_DELIVERY_REFUND_URL = '/delivery/refundDeliveryOfflineMapping.htm';

    const CRM_DELIVERY_MENU_URL = '/jcda/GetItemInfoList.htm';

    /**
     * 请求来源-客至提供
     */
    protected $SysType;
    /**
     * 接口根地址
     * @var string
     */
    protected $BaseUrl;
    /**
     * 商户编码-吾享提供
     */
    protected $AesKey;

    /**
     * http Client
     * @var
     */
    protected $httpClient;

    public function __construct(ClientFactory $clientFactory)
    {
        parent::__construct();
        if (env('APP_ENV') == 'dev') {  //开发环境
            $this->SysType = '56465YLXP542';
            $this->AesKey = 'EH60ZBDJDI2LOQD64VIFSNQR3H26APZ4';
            $this->BaseUrl = 'http://alpha.wuuxiang.com/api/external';
        } else {
            $this->SysType = '8765YLXP65446';
            $this->AesKey = 'MGDKMSFDRP0YR0RT9T5ADOGOVUASP6BB';
            $this->BaseUrl = 'http://o2oapi.wuuxiang.com/external';  //正式服
        }
        $this->httpClient = $clientFactory->create(['base_uri' => $this->BaseUrl, 'headers' => ['Content-Type' => 'application/json'], 'timeout' => 30.0]);
    }

    /**
     * 生成外卖单接口（不对接基础档案）
     * @param array $orderInfo
     * @param array $temp_data
     * @return mixed
     */
    public function deliveryInsertOfflineMapping(array $orderInfo, array $temp_data)
    {
        $orderInfo['action'] = 'pay';
        $post_data = [];
        $post_data['systype'] = $this->SysType;
        if ($temp_data) {
            $encrypt_data = $this->encrypt($temp_data);
            $post_data['data'] = $encrypt_data;
        }
        $post_url = $this->BaseUrl . self::CRM_DELIVERY_URL;
        $res = $this->http_post_json($post_url, $post_data);
        $param = json_encode($temp_data, JSON_UNESCAPED_UNICODE );
        if ($res['code'] == 1) {
            $decrypt_data = $this->decrypt($res['data']);
            $ress = json_decode($decrypt_data, true);
            if ($ress['returnCode'] != 1) {
                $this->eventDispatcher->dispatch(new WxPush($this->insertData($orderInfo, $param, $decrypt_data,2)));
                return [
                    'code' => 0,
                    'errorCode' => ErrorCode::SYSTEM_INVALID,
                    'throw' => "外卖推送下单异常\n".__METHOD__ . ":line:".__LINE__."\n".
                        "订单编号[向下]\n{$orderInfo['order_no']}\n".
                        "请求返回[向下]\n{$decrypt_data}\n".
                        "请求参数[向下]\n{$param}",
                    'msg' => $ress['errorText']
                ];
            }
            $this->eventDispatcher->dispatch(new WxPush($this->insertData($orderInfo, $param, $decrypt_data,1)));
            return ['code' => 1, 'msg' => '外卖推送下单成功', 'data' => $ress];
        }else {
            $this->eventDispatcher->dispatch(new WxPush($this->insertData($orderInfo, $param, json_encode($res, JSON_UNESCAPED_UNICODE),2)));
            return [
                'code' => 0,
                'errorCode' => ErrorCode::SYSTEM_INVALID,
                'throw' => "外卖推送下单异常\n".__METHOD__ . ":line:{$res['line']}\n".
                    "订单编号[向下]\n{$orderInfo['order_no']}\n".
                    "请求返回[向下]\n{$res['msg']}\n".
                    "请求参数[向下]\n{$param}",
                'msg' => $res['msg']
            ];
        }

    }

    /**
     * 2.5生成外卖单退款接口（不对接基础档案）
     * @param array $orderInfo
     * @param array $temp_data
     * @return mixed
     */
    public function refundDeliveryOfflineMapping(array $orderInfo, array $temp_data)
    {
        $orderInfo['action'] = 'refund';
        $post_data = [];
        $post_data['systype'] = $this->SysType;
        if ($temp_data) {
            $encrypt_data = $this->encrypt($temp_data);
            $post_data['data'] = $encrypt_data;
        }
        $post_url = $this->BaseUrl . self::CRM_DELIVERY_REFUND_URL;
        $res = $this->http_post_json($post_url, $post_data);
        $param = json_encode($temp_data, JSON_UNESCAPED_UNICODE );
        if ($res['code'] == 1) {
            $decrypt_data = $this->decrypt($res['data']);
            $ress = json_decode($decrypt_data, true);
            if ($ress['returnCode'] != 1) {
                $this->eventDispatcher->dispatch(new WxPush($this->insertData($orderInfo, $param, $decrypt_data,2)));
                return [
                    'code' => 0,
                    'errorCode' => ErrorCode::SYSTEM_INVALID,
                    'data' => $ress,
                    'throw' => "外卖退款推送异常\n".__METHOD__ . ":line:".__LINE__."\n".
                        "订单编号[向下]\n{$orderInfo['order_no']}\n".
                        "请求返回[向下]\n{$decrypt_data}\n".
                        "请求参数[向下]\n{$param}",
                    'msg' => '外卖退款推送失败'
                ];
            }
            $this->eventDispatcher->dispatch(new WxPush($this->insertData($orderInfo, $param, $decrypt_data,1)));
            return ['code' => 1, 'msg' => '外卖退款推送成功', 'data' => $ress];
        } else {
            $this->eventDispatcher->dispatch(new WxPush($this->insertData($orderInfo, $param, json_encode($res, JSON_UNESCAPED_UNICODE),2)));
            return [
                'code' => 0,
                'errorCode' => ErrorCode::SYSTEM_INVALID,
                'data' => ['errorText' => $res['msg']],
                'throw' => "外卖退款推送异常\n".__METHOD__ . ":line:{$res['line']}\n".
                    "订单编号[向下]\n{$orderInfo['order_no']}\n".
                    "请求返回[向下]\n{$res['msg']}\n".
                    "请求参数[向下]\n{$param}",
                'msg' => '外卖退款推送失败'
            ];
        }
    }

    /**
     * 生成外卖单接口（不对接基础档案）
     * @param $temp_data
     * @return mixed
     */
    public function GetItemInfoList($temp_data)
    {
        $post_data = [];
        $post_data['systype'] = $this->SysType;
        if ($temp_data) {
            $encrypt_data = $this->encrypt($temp_data);
            $post_data['data'] = $encrypt_data;
        }
        $post_url = $this->BaseUrl . self::CRM_DELIVERY_MENU_URL;
        $res = $this->http_post_json($post_url, $post_data);
        if ($res['code'] == 1) {
            $decrypt_data = $this->decrypt($res['data']);
            return json_decode($decrypt_data, true);
        } else {
            throw new RefundException($res['msg'], $res['errorCode']);
        }

    }

    /**
     * post json 格式数据
     * $url url 地址
     * $jsonStr json 字符串
     * @param $url
     * @param $post_data
     * @return mixed
     */
    public function http_post_json($url, $post_data)
    {
        try {
            $headers = [
                'Content-Type: application/x-www-form-urlencoded',
            ];
            $options = [
                'headers' => $headers,
                'form_params' => $post_data
            ];
            $httpResponse = $this->httpClient->post($url, $options);
        } catch (ClientException $e) {
            return ['code' => 0, 'errorCode' => ErrorCode::SYSTEM_INVALID, 'msg' => $e->getMessage(), 'line' =>$e->getLine()];
        } catch (ServerException $e) {
            return ['code' => 0, 'errorCode' => ErrorCode::SYSTEM_INVALID, 'msg' => $e->getMessage(), 'line' =>$e->getLine()];
        } catch (\Throwable $t) {
            return ['code' => 0, 'errorCode' => ErrorCode::SYSTEM_INVALID, 'msg' => $t->getMessage(), 'line' =>$t->getLine()];
        }
        return ['code' => 1, 'msg' => '外卖退单推送成功', 'data' => $httpResponse->getBody()->getContents()];
    }

    /**
     * 加密 长数据加密(117)
     * @param array $originalData
     * @return string|void
     */
    public function encrypt($originalData)
    {
        $rsaPublicKey = $this->AesKey;
        $data = json_encode($originalData);
        $mess = WxCryptService::encrypt($data, $rsaPublicKey);
        return $mess;
    }

    /**
     * 解密 长数据解密(128)
     * @param string $encryptData
     * @return string|void
     */
    public function decrypt($encryptData)
    {
        $rsaPublicKey = $this->AesKey;
        $res = WxCryptService::decrypt($encryptData, $rsaPublicKey);
        return $res;
    }

    /**
     * 组装入库数据（日志库）
     * @param array $orderInfo
     * @param string $param
     * @param string $res
     * @param int $type
     * @return array
     */
    public function insertData(array $orderInfo, string $param, string $res, int $type){

        if ($orderInfo['action'] == 'pay'){
            $ress = json_decode($res, true);
            $deId = $ress['deid'] ?? '';
            $deNo = $ress['deNo'] ?? '';
            $posType = 1;
        }else{
            $ress = json_decode($param, true);
            $deId = $ress['deID'] ?? '';
            $deNo = $ress['deNo'] ?? '';
            $posType = 2;
        }

        return [
            'order_no' => $orderInfo['order_no'],
            'shop_id' => $orderInfo['shop_id'],
            'params_detail' => $param,
            'res_detail' => $res,
            'deId' => $deId,
            'deNo' => $deNo,
            'type' => $type,
            'pos_type' => $posType,
            'pay_type' => $orderInfo['pay_type']
        ];
    }

}